/*
 * @Author: xuhua
 * @Date: 2023-09-13 13:54:38
 * @LastEditors: xuhua
 * @LastEditTime: 2023-09-19 10:45:10
 * @FilePath: /v3-element-admin/src/utils/request/index.ts
 * @Description: axios封装
 */
import axios from "axios";
import type { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from "axios";

import { useEnv } from "@/hooks/useEnv";
import { ElMessage, ElMessageBox } from "element-plus";

interface axiosConfig {
	successMessage?: boolean;
	errorMessage?: boolean;
	cancelSame?: boolean;
	retryCount?: number;
	isRetry?: boolean;
	loading?: boolean;
}

const defaultConfig: axiosConfig = {
	successMessage: false,
	errorMessage: true,
	cancelSame: false,
	isRetry: false,
	retryCount: 3,
	loading: true,
};

const { VITE_APP_BASE_API } = useEnv();

// 创建实例
const service: AxiosInstance = axios.create({
	baseURL: VITE_APP_BASE_API,
	timeout: 60 * 1000,
	headers: {
		"Content-Type": "application/json;charset=UTF-8",
	},
});

// 请求拦截器
service.interceptors.request.use(
	(config: InternalAxiosRequestConfig) => {
		const token = localStorage.getItem("accessToken");
		// config.params = {
		// 	_t: new Date().getTime(),
		// };
		if (token) {
			config!.headers!.Authorization = token ?? "";
		}

		return config;
	},
	(error) => {
		return Promise.reject(error);
	}
);

// 响应拦截器
service.interceptors.response.use(
	(response: AxiosResponse) => {
		const data = response.data;
		if (data.code == "200") {
			return data;
		}

		// 响应数据为二进制流处理(Excel导出)
		if (response.data instanceof ArrayBuffer) {
			return response;
		}

		ElMessage.error(data.message || "系统错误!");
		return Promise.reject(new Error(data.message || "系统错误!"));
	},
	(error) => {
		if (error.response.data) {
			const { code, msg } = error.response.data;
			// token 过期，跳转登录页
			if (code === "401") {
				ElMessageBox.confirm("当前页面已失效，请重新登录", "提示", {
					confirmButtonText: "确定",
					type: "warning",
				}).then(() => {
					localStorage.clear(); // @vueuse/core 自动导入
					window.location.href = "/";
				});
			} else {
				ElMessage.error(msg || "系统出错");
			}
		}
		return Promise.reject(error.message);
	}
);

// 封装get,post,put,delete,request通用请求,可使用xxx.get().xxx.post()
const request = {
	get<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request("GET", url, { params: { ...data, _t: new Date().getTime() } }, config);
	},
	post<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request("POST", url, { data }, config);
	},
	put<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request("PUT", url, { data }, config);
	},
	delete<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request("DELETE", url, { params: data }, config);
	},
	request<T = any>(method = "GET", url: string, data?: any, config?: axiosConfig): Promise<T> {
		const options = Object.assign({}, defaultConfig, config);
		return new Promise((resolve, reject) => {
			service({ method, url, ...data, requsetOptions: options })
				.then((res) => {
					resolve(res as unknown as Promise<T>);
				})
				.catch((e: Error | AxiosError) => {
					reject(e);
				})
				.finally(() => {
					// TODO 关闭loading
					// if(options.loading){
					// 	axiosLoading.closeLoading();
					// }
				});
		});
	},
};

export default request;
